/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：太平金科-基础组件封装层-SpringBoot组件封装-缺省实现
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taipingframework.boot.web.servlets;

import com.taipingframework.boot.web.response.result.ApiResult;
import com.taipingframework.boot.web.response.status.ApiStatusEnum;
import com.taipingframework.utility.exception.ApplicationException;
import com.taipingframework.utility.thread.ForkJoinHelper;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.List;
import java.util.TreeMap;
import java.util.stream.Collectors;

// 特别说明：
// - 添加`@Controller`注解是为了使切面能够拦截到`/path/list`的请求。
// - 为避免冲突，禁止MvcPathController再被`@ComponentScan`扫描到，它在SpringWebMvcAutoConfiguration中已经被显式声明为java bean。
@Controller
@RequestMapping("/project")
public class MvcPathController {

    private final RequestMappingHandlerMapping requestMappingHandlerMapping;

    public MvcPathController(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }

    /**
     * 获取 spring-webmvc工程中所有的Api-Path列表
     */
    @ResponseBody
    @RequestMapping("/path/list")
    public ApiResult<TreeMap<String, List<String>>> readApiList() throws ApplicationException {
        try {
            return ApiResult.<TreeMap<String, List<String>>>build()
                    .setStatus(ApiStatusEnum.SUCCESS)
                    .setResult(ForkJoinHelper.execute(() -> requestMappingHandlerMapping.getHandlerMethods()
                            .entrySet()
                            .parallelStream()
                            .collect(Collectors.toMap(
                                    entry -> entry.getValue().getMethod().toGenericString(),
                                    entry -> entry.getKey()
                                            .getPatternsCondition()
                                            .getPatterns()
                                            .parallelStream()
                                            .collect(Collectors.toList()),
                                    (oldValue, newValue) -> newValue,
                                    TreeMap::new
                                    )
                            ))
                    );
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

}
